#include<iostream>
#include<cstdlib>
#include<cerrno>
#include<cstring>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
using namespace std;

const char *pathname = "/root/code/shm_ipc";
const int proj_id = 0x8888;

//在内核中，共享内存的大小是以4kb为基本单位的，自己只能用自己的申请大小，建议申请大小是n*4kb
const int defaultsize = 4096;//字节

std::string ToHex(key_t k)
{
    char buffer[1024];
    snprintf(buffer,sizeof(buffer),"0x%x",k);
    return buffer;
}

key_t Getshmkeyordie()
{
    key_t k = ftok(pathname,proj_id);
    if(k<0)
    {
        std::cout<<"ftok error,errno:"<<errno<<",error string:"<<strerror(errno)<<std::endl;
        exit(1);
    }
    return k;
}
int Createshmordie(key_t key, int size,int flag)
{
    int shmid = shmget(key,size,flag);
    if(shmid<0)
    {
        std::cout<<"shmget error,errno:"<<errno<<",error string:"<<strerror(errno)<<std::endl;
        exit(2);
    }
    return shmid;
}
int createShm(key_t key,int size)
{
    //IPC_CREAT:不存在就不创建，存在就获取
     //IPC_EXCL：没有意义
     //IPC_CREAT|IPC_EXCL：不存在就创建，存在就出错返回；
    return Createshmordie(key,size,IPC_CREAT|IPC_EXCL|0666);
}
int Getshm(key_t key,int size)
{
    return Createshmordie(key,size,IPC_CREAT);
}
void Deleteshm(int shmid)//删除
{
    int n =shmctl(shmid,IPC_CREAT,nullptr);
    if(n<0)
    {
        std::cerr<<"shmctl error"<<std::endl;
    }
    else
    {
        std::cout<<"shmctl delete shm success shmid:"<<shmid<<std::endl;
    }
}
void ShmDebug(int shmid)
{
    struct shmid_ds shmds;
    int n = shmctl(shmid,IPC_CREAT,&shmds);
    if(n<0)
    {
        std::cout<<"shmds.shm_segsz:"<<shmds.shm_segsz<<std::endl;
        std::cout<<"shmds.shm_nattch:"<<shmds.shm_nattch<<std::endl;
        std::cout<<"shmds.shm_ctime:"<<shmds.shm_ctime<<std::endl;
        std::cout<<"shmds.shm_perm.__key:"<<shmds.shm_perm.__key<<std::endl;
    }
}
void *ShmAttach(int shmid)
{
    void *addr = shmat(shmid,nullptr,0);
    if((long long int)addr ==-1)
    {
        std::cerr<<"shat error"<<std::endl;
       return nullptr;
    }
    return addr;
}
void ShmDetach(void *addr)
{
    int n = shmdt(addr);
    if(n<0)
    {
        std::cerr<<"shmdt error"<<std::endl;
    }
}